package org.springblade.modules.admin.controller.erp;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.admin.dto.erp.*;
import org.springblade.modules.admin.dto.erp.serivce.MultiplyBuyingLeadsDTO;
import org.springblade.modules.admin.dto.erp.serivce.PartnerCloudPartsSkuSyncDTO;
import org.springblade.modules.admin.enums.erp.ERPTableEnum;
import org.springblade.modules.admin.enums.erp.options.BuildingMessageTypeEnum;
import org.springblade.modules.admin.enums.erp.tables.BuildingMessageEnum;
import org.springblade.modules.admin.service.BuildingService;
import org.springblade.modules.admin.service.IMaintainPartService;
import org.springblade.modules.admin.service.erp.IPartnerCloudPartsService;
import org.springblade.modules.admin.service.erp.IPartnerCloudSpaceTableService;
import org.springblade.modules.admin.task.erp.PartnerCloudBuildingMessageJob;
import org.springblade.modules.admin.utils.erp.Decrypt;
import org.springblade.modules.admin.vo.erp.PartnerCloudCallBackVO;
import org.springblade.modules.admin.vo.erp.service.*;
import org.springblade.modules.admin.vo.erp.tables.PartnerCloudTableItemListVO;
import org.springblade.modules.admin.vo.erp.tables.PartnerCloudTableItemVO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 伙伴云订阅控制器
 * @author Sharry
 * @since 2024-12-20
 */
@Slf4j
@Component
@ResponseBody
@RequiredArgsConstructor
@RequestMapping("/erp/cloud")
@Api(value = "/erp/cloud", tags = "erp-伙伴云接口")
public class PartnerCloudSearchController {

	@Value("${erp.api_key}")
	private String apiKey;

	@Value("${erp.prefix_url}")
	private String prefixUrl;

	@Value("${erp.encrypt_key}")
	private String encryptKey;

	@Resource
	private BuildingService buildingService;

	@Resource
	private IPartnerCloudSpaceTableService partnerTableService;

	@Resource
	private IPartnerCloudPartsService partnerPartsService;

	@Resource
	private PartnerCloudBuildingMessageJob partnerCloudBuildingMessageJob;

	/**
	 * 手动同步配件任务列表
	 */
	@GetMapping("/parts/task/list")
	@ApiOperation("手动同步配件任务列表")
	@ApiOperationSupport(order = 0)
	private void pushPartsTask() {
		partnerCloudBuildingMessageJob.partnerCloudPartsTaskListJob();
	}

	@GetMapping("/building/message/init")
	@ApiOperation("初始化项目表，正式环境执行")
	@ApiOperationSupport(order = 1)
	private R<Boolean> initBuildingMessage(){
		isProdEnv();
		String tableId = ERPTableEnum.BUILDING_MESSAGE.getTableId();
		// 1. 查询数据
		List<BuildingMessageVO> buildingMessageVOList = buildingService.selectBuildingMessageList();
		// 现有的数据
		PartnerCloudTableSearchFullDTO searchFullDTO = new PartnerCloudTableSearchFullDTO();
		searchFullDTO.setTable_id(tableId);
		PartnerCloudTableItemListVO partnerCloudTableItemListVO = partnerTableService.searchFullTable(searchFullDTO);
		List<String> deleteIds = new ArrayList<>();
		if(!Func.isNull(partnerCloudTableItemListVO)){
			List<PartnerCloudTableItemVO> items = partnerCloudTableItemListVO.getItems();
			if(Func.isNotEmpty(items)){
				// 获取现有数据中的 item_id + fields 的 项目id 列表
				List<String> collect = items.stream().map(PartnerCloudTableItemVO::getItem_id).collect(Collectors.toList());
				deleteIds.addAll(collect);
			}
		}
		// 2. 处理数据/数据封装
		PartnerCloudTableSaveOrUpdateDTO saveOrUpdateDTO = new PartnerCloudTableSaveOrUpdateDTO();
		saveOrUpdateDTO.setTable_id(tableId);
		List<String> updateFields = new ArrayList<>();
		updateFields.add(BuildingMessageEnum.BUILDING_ID.getFieldId());
		saveOrUpdateDTO.setUpdate_by_fields(updateFields);
		List<PartnerCloudTableItemDTO> items = new ArrayList<>();

		// 处理数据并封装
		if(Func.isNotEmpty(buildingMessageVOList)){
			for(BuildingMessageVO buildingMessageVO : buildingMessageVOList){
				PartnerCloudTableItemDTO item = new PartnerCloudTableItemDTO();
				Map<String,Object> fields = new HashMap<>(10);
				fields.put(BuildingMessageEnum.BUILDING_ID.getFieldId(), buildingMessageVO.getBuildingId());
				fields.put(BuildingMessageEnum.BUILDING_NAME.getFieldId(), buildingMessageVO.getBuildingName());
				fields.put(BuildingMessageEnum.USE_UNIT.getFieldId(), buildingMessageVO.getUserUnitName());
				fields.put(BuildingMessageEnum.CONTACT_PERSON.getFieldId(), buildingMessageVO.getContactsName());
				fields.put(BuildingMessageEnum.PHONE.getFieldId(), buildingMessageVO.getPhone());
				fields.put(BuildingMessageEnum.ADDRESS.getFieldId(), buildingMessageVO.getAddress());
				String type = buildingMessageVO.getBuildingType();
				if(!Func.isNull(type)){
					List<String> typeList = new ArrayList<>();
					String idByDictKey = BuildingMessageTypeEnum.getIdByDictKey(type);
					typeList.add(idByDictKey);
					fields.put(BuildingMessageEnum.TYPE.getFieldId(),typeList);
				}
				item.setFields(fields);
				items.add(item);
			}
		}
		saveOrUpdateDTO.setItems(items);
		// 3. 先删除全量，再新增或更新
		PartnerCloudTableDeleteBatchDTO deleteBatchDTO = new PartnerCloudTableDeleteBatchDTO();
		deleteBatchDTO.setTable_id(tableId);
		deleteBatchDTO.setItem_ids(deleteIds);
		// 2025-01-09 注释掉，暂时不用删除，仅更新
//		partnerTableService.deleteTableItemsBatch(deleteBatchDTO);
		return R.data(partnerTableService.saveOrUpdateByFields(saveOrUpdateDTO));
	}

	/**
	 * 初始化配件SKU列表
	 */
	@GetMapping("/parts/sku/init")
	@ApiOperation("初始化配件SKU列表")
	@ApiOperationSupport(order = 2)
	private R<Boolean> initPartsSku() {
		isProdEnv();
		String tableId = ERPTableEnum.PRODUCT_INFORMATION.getTableId();
		// 1. 现有的数据
		PartnerCloudTableSearchFullDTO searchFullDTO = new PartnerCloudTableSearchFullDTO();
		searchFullDTO.setTable_id(tableId);
		PartnerCloudTableItemListVO partnerCloudTableItemListVO = partnerTableService.searchFullTable(searchFullDTO);
		List<String> deleteIds = new ArrayList<>();
		if(!Func.isNull(partnerCloudTableItemListVO)){
			List<PartnerCloudTableItemVO> items = partnerCloudTableItemListVO.getItems();
			if(Func.isNotEmpty(items)){
				// 获取现有数据中的 item_id + fields 的 项目id 列表
				List<String> collect = items.stream().map(PartnerCloudTableItemVO::getItem_id).collect(Collectors.toList());
				deleteIds.addAll(collect);
			}
		}
		// 2. 先删除全量，再新增或更新
		PartnerCloudTableDeleteBatchDTO deleteBatchDTO = new PartnerCloudTableDeleteBatchDTO();
		deleteBatchDTO.setTable_id(tableId);
		deleteBatchDTO.setItem_ids(deleteIds);
		// 3. 发送 请求到 配件商城项目，全量新增
		HttpUtil.createGet("https://parts.sida-tech.com/api/erp/partner/cloud/purchase/sku/list").execute();
		return R.data(partnerTableService.deleteTableItemsBatch(deleteBatchDTO));
	}

	/**
	 * 同步配件SKU列表
	 */
	@PostMapping("/parts/sku/purchase")
	@ApiOperation("同步配件SKU列表")
	@ApiOperationSupport(order = 2)
	private R<Void> syncPartsSku(@RequestBody PartnerCloudPartsSkuSyncDTO partsSkuSyncDTO){
		log.warn("接收到配件SKU同步ERP请求, partsSkuSyncDTO={}", partsSkuSyncDTO);
		try{
			// 2025-02-20 新增同步 同步系统id到ERP 逻辑
			partnerPartsService.sendPartsSkuId(partsSkuSyncDTO);
			partnerPartsService.syncPartsSku(partsSkuSyncDTO);
		}catch (Exception e){
			log.error("配件SKU同步ERP失败", e);
			throw new ServiceException("配件SKU同步ERP失败" + e);
		}
		return R.data(null);
	}

	@GetMapping("/parts/work/purchase")
	@ApiOperation("采购需求同步ERP接口")
	@ApiOperationSupport(order = 3)
	private R<Void> purchase(@RequestParam Long planId){
		log.warn("接收到新结构采购需求同步ERP请求, planId={}", planId);
		// 预留，未来读租户-业务配置，当前写死
		String tenantId = "592800";
		partnerPartsService.syncMultiplyPurchase(planId,tenantId);
		return R.data(null);

	}

	/**
	 * 旧的同步逻辑，先放这里，不调用
	 * @param planId 工单id
	 * @return R<Void>
	 */
	@GetMapping("/parts/work/multiply/purchase")
	@ApiOperation("旧结构采购需求同步ERP接口")
	@ApiOperationSupport(order = 4)
	private R<Void> multiplyPurchase(@RequestParam Long planId){
		log.warn("接收到采购需求同步ERP请求, planId={}", planId);
		partnerPartsService.syncPurchase(planId);
		return R.data(null);
	}

	@PostMapping("/test/getInfo")
	@ApiOperation("测试接口")
	@ApiOperationSupport(order = 5)
	private R<Boolean> getInfo(@RequestBody JSONObject resultJsonObject){
		return R.data(partnerPartsService.analyzeCallBackData(resultJsonObject));
	}

	/**
	 * 回调接口
	 */
	@ApiOperation("回调接口")
	@PostMapping("/callback")
	@ApiOperationSupport(order = 10)
	public PartnerCloudCallBackVO callback(@RequestBody PartnerCloudCallBackDTO callBackDTO) {
		String challenge = "challenge";
		if(Func.isNull(callBackDTO.getEncrypted())){
			PartnerCloudCallBackVO result = new PartnerCloudCallBackVO();
			result.setChallenge(callBackDTO.getChallenge());
			return result;
		}
		String encrypted = callBackDTO.getEncrypted();
		Decrypt decrypt = new Decrypt(encryptKey);
		try {
			String decryptResult = decrypt.decrypt(encrypted);
			// 将 decryptResult 字符串转换成 JSONObject
			JSONObject resultJsonObject = JSONObject.parseObject(decryptResult);
			// 若是 challenge，则返回 challenge
			if(resultJsonObject.containsKey(challenge)){
				PartnerCloudCallBackVO result = new PartnerCloudCallBackVO();
				result.setChallenge(resultJsonObject.getString(challenge));
				return result;
			}
			log.warn("伙伴云回调数据即将进行处理：{}", resultJsonObject);
			Boolean isSuccess =  partnerPartsService.analyzeCallBackData(resultJsonObject);
			// 回调数据处理完成，返回结果
			log.warn("伙伴云回调数据处理完成，结果：{}", isSuccess);
		} catch (Exception e) {
			log.error("伙伴云回调解密失败", e);
			throw new ServiceException("伙伴云有回调解密失败" + e);
		}
		return null;
	}

	/**
	 * 添加订阅
	 */
	 @PostMapping("/subscribe")
	 @ApiOperation("添加订阅")
	 @ApiOperationSupport(order = 11)
	 public R<JSONObject> subscribe(@RequestBody PartnerCloudSubscribeDTO subscribeDTO) {
		 String url = prefixUrl + "/event/subscribe";
		 String authorization = "Bearer " + apiKey;
		 String bodyJson = JSONObject.toJSONString(subscribeDTO);
		 String result = HttpRequest.post(url)
			 .header("Open-Authorization", authorization)
			 .header("Content-Type", "application/json;charset=UTF-8")
			 .body(bodyJson)
			 .execute()
			 .body();
		 return R.data(JSONObject.parseObject(result));
	 }

	/**
	 * 删除订阅
	 */
	@PostMapping("/subscribe/delete")
	@ApiOperation("删除订阅")
	@ApiOperationSupport(order = 20)
	public R<JSONObject> unsubscribe(@RequestBody PartnerCloudSubscribeDTO subscribeDTO) {
		String url = prefixUrl + "/event/unsubscribe";
		String authorization = "Bearer " + apiKey;
		String bodyJson = JSONObject.toJSONString(subscribeDTO);
		String result = HttpRequest.post(url)
			.header("Open-Authorization", authorization)
			.header("Content-Type", "application/json;charset=UTF-8")
			.body(bodyJson)
			.execute()
			.body();
		return R.data(JSONObject.parseObject(result));
	}

	/**
	 * 获取订阅列表
	 */
	@PostMapping("/subscribe/list")
	@ApiOperation("订阅列表")
	@ApiOperationSupport(order = 40)
	public R<JSONObject> subscribeList(@RequestBody PartnerCloudSubscribeDTO subscribeDTO) {
		String url = prefixUrl + "/event/list";
		String authorization = "Bearer " + apiKey;
		String bodyJson = JSONObject.toJSONString(subscribeDTO);
		String result = HttpRequest.post(url)
			.header("Open-Authorization", authorization)
			.header("Content-Type", "application/json;charset=UTF-8")
			.body(bodyJson)
			.execute()
			.body();
		return R.data(JSONObject.parseObject(result));
	}

	private void isProdEnv(){
		String prodEnv = "prod";
		String activeProfile = System.getProperty("spring.profiles.active");
		log.info("当前环境为：{}", activeProfile);
		if (!prodEnv.equals(activeProfile)){
			throw new ServiceException("非正式环境不能对伙伴云ERP进行操作!");
		}
	}

	/**
	 * 根据订单号，查询伙伴云相关的订单信息
	 */
	@GetMapping("/search/order")
	@ApiOperation("根据订单号查询伙伴云相关的订单信息")
	@ApiOperationSupport(order = 41)
	public R<List<SalesOrderSearchVO>> searchOrderByOrderId(String orderId){
		if(Func.isBlank(orderId)){
			throw new ServiceException("订单号不能为空!");
		}
		return R.data(partnerPartsService.searchOrderByOrderId(orderId));
	}

	/**
	 * 为了响应性能，将三处请求合拆分为3个接口
	 * 根据订单号单独查询伙伴云订单主表信息
	 */
	@GetMapping("/search/order/main")
	@ApiOperation("根据订单号单独查询伙伴云订单主表信息")
	@ApiOperationSupport(order = 42)
	public R<List<SalesOrderSearchVO>> searchOrderMainByOrderId(String orderId){
		if(Func.isBlank(orderId)){
			throw new ServiceException("订单号不能为空!");
		}
		return R.data(partnerPartsService.searchOrderMainByOrderId(orderId));
	}

	/**
	 * 根据订单号单独查询伙伴云订单子表信息
	 */
	@GetMapping("/search/order/sub")
	@ApiOperation("根据订单号单独查询伙伴云订单子表信息")
	@ApiOperationSupport(order = 43)
	public R<List<DeliveryVO>> searchOrderSubByOrderId(String orderId){
		if(Func.isBlank(orderId)){
			throw new ServiceException("订单号不能为空!");
		}
		return R.data(partnerPartsService.searchDeliveryByOrderId(orderId));
	}

	/**
	 * 根据出单号单独查询伙伴云出单明细表
	 */
	@GetMapping("/search/delivery/detail")
	@ApiOperation("根据出单号单独查询伙伴云出单明细表")
	@ApiOperationSupport(order = 44)
	public R<List<ShipmentDetailVO>> searchDeliveryDetailByDeliveryId(String deliveryNote){
		if(Func.isBlank(deliveryNote)){
			throw new ServiceException("出单号不能为空!");
		}
		return R.data(partnerPartsService.searchShipmentDetailByDeliveryNote(deliveryNote));
	}
}
